#include "flash.h"

u16 FLASH_BUF[SECTOR_SIZE/2]; //1KByte




//提供给用户的函数
void FLASH_Write(u32 Addr,u16 *pBuff,u16 len)
{
	u32 Sector_Number;  //第几扇区
	u32 Sector_Relative;   //扇区内偏移地址（按16位计算）
	u32 Sector_Remain;     //扇区内剩余地址（按16位计算）
	u32 OffAddr;           //减去0x08000000后的地址
	u16 i;
	
	//判断地址合理性
	if(Addr<FLASH_BASE || Addr>=(FLASH_BASE+1024*F_SIZE))return; 
	
	FLASH_Unlock();
	
	OffAddr = Addr - FLASH_BASE;
	Sector_Number = OffAddr/SECTOR_SIZE;
	Sector_Relative = (OffAddr%SECTOR_SIZE)/2;
	Sector_Remain = SECTOR_SIZE/2-Sector_Relative;
	
	//如果一页能够写完
	if(len <= Sector_Remain) Sector_Remain = len;
	
	//写入
	while(1)
	{
		//整页读出
		FLASH_Read(Sector_Number*SECTOR_SIZE+FLASH_BASE,FLASH_BUF,SECTOR_SIZE/2);
		
		for(i=0;i<Sector_Remain;i++)
		{
			if(FLASH_BUF[Sector_Relative+i] != 0xFFFF) break; //需要擦除
		}
		if(i<Sector_Remain) //需要擦除
		{
			FLASH_ErasePage(Sector_Number*SECTOR_SIZE+FLASH_BASE);
			
			//替换数据
			for(i=0;i<Sector_Remain;i++)
			{
				FLASH_BUF[Sector_Relative+i] = pBuff[i];
			}
			
			//写入FLASH
			FLASH_Writ_NoCheck(Sector_Number*SECTOR_SIZE+FLASH_BASE,FLASH_BUF,SECTOR_SIZE/2);	
		}
		else
		{
			FLASH_Writ_NoCheck(Addr,pBuff,Sector_Remain);
		}
		
		if(len == Sector_Remain) break; //写入结束
		else
		{
			Sector_Number++;          //页+1
			Sector_Relative = 0;      //页内偏移0
			pBuff += Sector_Remain;   //更新传入的数组指针
			Addr += Sector_Remain*2;    //写地址偏移
			len -= Sector_Remain;     //更新写长度
			
			if(len>(SECTOR_SIZE/2)) Sector_Remain = SECTOR_SIZE/2;
			else Sector_Remain = len;
		}
	}
	
	FLASH_Lock();
}




//读取一个半字（16位）
u16 FLASH_ReadHalfWord(u32 faddr)
{
	return *(vu16*)faddr; 
}


//读出一段数据（16位）
void FLASH_Read(u32 Addr,u16 *pBuff,u16 len)
{
	u16 i;
	for(i=0;i<len;i++)
	{
		pBuff[i] = FLASH_ReadHalfWord(Addr);
		Addr += 2;
	}
}

#if FLSAH_EN_WRITE //如果使能了写

//不检查的写入
void FLASH_Writ_NoCheck(u32 Addr,u16 *pBuff,u16 len)
{
	u16 i;
	for(i=0;i<len;i++)
	{
		FLASH_ProgramHalfWord(Addr,pBuff[i]);
		Addr += 2;
	}
}

/************************************************个人加入************************************************/
#if 0
#define STARTADDR 0x08000000 //STM32F103C8T6适用

volatile FLASH_Status FLASHStatus = FLASH_BUSY; //Flash操作状态变量

/*
 * Name:	    WriteFlashOneWord
 * Function:	向内部Flash写入32位数据
 * Input:	    WriteAddress：数据要写入的目标地址（偏移地址）
 *              WriteData：   写入的数据
 */
void WriteFlashOneWord(uint32_t WriteAddress, uint32_t WriteData)
{   
    FLASH_UnlockBank1();
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);

    FLASHStatus = 1;    //清空状态指示标志位
    FLASHStatus = FLASH_ErasePage(STARTADDR);  
    if(FLASHStatus == FLASH_COMPLETE)   
    {  
        FLASHStatus = 1;    //清空状态指示标志位
        FLASHStatus = FLASH_ProgramWord(STARTADDR+WriteAddress, WriteData); //flash.c 中API函数
    }
    
    FLASHStatus = 1;    //清空状态指示标志位
    FLASH_LockBank1();    
}

/*
 * Name:	    WriteFlashData
 * Function:	向内部Flash写入数据
 * Input:	    WriteAddress：数据要写入的目标地址（偏移地址）
 *             data[]：      写入的数据首地址
 *             num：         写入数据的个数
 */
void WriteFlashData(uint32_t WriteAddress, uint8_t data[], uint32_t num)
{
    uint32_t i = 0;
    uint16_t temp = 0;
    
	FLASH_UnlockBank1();    //解锁flash
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); 
    
    FLASHStatus = 1;        //清空状态指示标志位
    FLASHStatus = FLASH_ErasePage(STARTADDR);//擦除整页
	if(FLASHStatus == FLASH_COMPLETE)//flash操作完成
	{
        FLASHStatus = 1;    //清空状态指示标志位
        for(i=0; i<num; i++)
        {
            temp = (uint16_t)data[i];
            FLASHStatus = FLASH_ProgramHalfWord(STARTADDR+WriteAddress+i*2, temp);//写入数据
        }
	}
    
    FLASHStatus = 1;    //清空状态指示标志位
    
	FLASH_LockBank1();  //锁定flash
} 
/*
 * Name:	    ReadFlashNBtye
 * Function:	从内部Flash读取N字节数据
 * Input:	    ReadAddress：数据地址（偏移地址）
 *              ReadBuf：读取到的数据存放位置指针
 *              ReadNum：读取字节个数
 * Output:      读取的字节数
 */
int ReadFlashNBtye(uint32_t ReadAddress, uint8_t *ReadBuf, int32_t ReadNum)
{   
    int DataNum = 0;
    
    ReadAddress = (uint32_t)STARTADDR + ReadAddress;  
    while(DataNum < ReadNum)   
    {        
        *(ReadBuf + DataNum) = *(__IO uint8_t*) ReadAddress++;  
        DataNum++;     
    }
    
    return DataNum;    
}

/*
 * Name:	    ReadFlashData
 * Function:	从内部Flash读取num字节数据
 * Input:	    ReadAddress：数据地址（偏移地址）
 *              dest_Data：  读取到的数据存放位置指针
 *              num：        读取字节个数
 */
void ReadFlashData(uint32_t ReadAddress, uint8_t *dest_Data, uint32_t num)
{
    int i = 0;
    ReadAddress = (uint32_t)STARTADDR + ReadAddress; 
    while(i < num) 
    {
        *(dest_Data+i) = *(__IO uint16_t*) ReadAddress;
        ReadAddress += 2;
        
        i++;
    }
}
#endif


#endif


























